<html>
    <head>
        <title>选项牧师</title>
    </head>
    <body>
        <script>
            // 选项模式  Options

                    /*
                         Microsoft 引入了"选项模式",该模式用于配置框架服务使用的一组设置。
                         该模式有 Microsoft.Enents.Options NuGet包实现，因此除了基于核心的应用程序之外，，它还可用于任何类型的基于asp.net的应用程序。

                         ABP遵循这种选项模式，并定义"选项类"来配置框架和模块 （它们在相关功能的文档中进行了解释）

                         由于Microsoft 文档中详细解释了该模式，因此没有理由全部重复。  然而，ABP添加了更多功能，它们将在此处解释。
                    */

                    /*
                        一、选项类

                                在选项模式中，可以使用一个"普通的类"，有时也称为"POCO"（Plain Old CLR Object) 来定义一组选项。

                                定义选项类：

                                    public class AbpAduitingOptions
                                    {
                                        // 选项就是属性
                                        public string Sender {get;set;}
                                        
                                        public bool IsEnabled {get;set;}
                                    }

                                为选项类名称中添加 "Options"后缀是一种惯例，也可以说是约定。
                    */


                    /*
                        二、配置选项

                                在 asp.net core中， 你通常在 Startup 类中的ConfigureServices中配置选项。
                                但是，由于ABP提供了模块化基础架构，因此你可以在模块的 ConfigureServices中配置选项。
                                eg:
                                    public override void ConfigureServices(ServiceConfigurationContext context)
                                    {
                                        context.Services.Configure<AbpAuditingOptions>(options =>
                                        {
                                            options.IsEnabled = false;
                                        });
                                    }

                                AbpAuditingOptions是一个简单的类，定义了一些属性，例如这里使用的IsEnabled。

                                AbpModule基类定义了Configure方法，使代码更简单，所以，代替context.Services.Configure<...>，可以直接使用Configure<...>快捷方式。


                                如果你正在开发一个可重用的模块，你可能需要定义一个选项类来允许开发人员来配置你的模块。
                                在这种情况下，定义一个普通的选项类，如下所示：

                                    public class MyOptions
                                    {
                                        public int Value1 { get; set; }
                                        public bool Value2 { get; set; }
                                    }

                                然后开发人员可以像上面的AbpAuditingOptions示例一样配置你的选项：

                                    public override void ConfigureServices(ServiceConfigurationContext context)
                                    {
                                        Configure<MyOptions>(options =>
                                        {
                                            options.Value1 = 42;
                                            options.Value2 = true;
                                        });
                                    }
                    */

                    /*
                        三、如何获取选项值

                                每当你想获取选项值时，将 IOptions<TOptions> 服务注入到你的类并直接使用其 ".Value"属性即可。

                                    public class MyService : ITransientDependency
                                    {
                                        private readonly MyOptions _options;
                                        
                                        public MyService(IOptions<MyOptions> options)
                                        {
                                            _options = options.Value; //Notice the options.Value usage!
                                        }

                                        public void DoIt()
                                        {
                                            var v1 = _options.Value1;
                                            var v2 = _options.Value2;
                                        }
                                    }

                                由此可见，当前选项对象时整个应用程序范围的单一实例，并被所有注入它的类共享。
                    */

                    /*
                        四、预配置
                                选项模式的一个限制是，你只能在依赖项注入且配置完成后注入IOptions<TOptions>才能获取选项值。(这意味着必须等所有模块的 ConfigureServices方法执行完成后才行)

                                如果你正在开发一个模块，你可能需要允许开发人员设置一些选项，并在依赖注入注册阶段使用这些配置。
                                （你可能需要配置其他服务或根据这些选项值更改依赖注入注册代码。）

                                对于这种情况，ABP 为IServiceCollection引入了 PreConfigure<TOptions> 和 ExecutePreConfiguredActions<TOptions>扩展方法。
                                该模式的工作原理如下所述：

                                    1、在模块中定义一个"预配置选项类"：
                                            public class MyPreOptions
                                            {
                                                public bool MyValue { get; set; }
                                            }

                                    2、然后任何依赖你模块的"模块类"都可以在其 PreConfigureServices 方法中使用 PreConfigure<TOptions>方法。
                                            eg：
                                                public override void PreConfigureServices(ServiceConfigurationContext context)
                                                {
                                                    PreConfigure<MyPreOptions>(options =>
                                                    {
                                                        options.MyValue = true;
                                                    });
                                                }

                                            多个模块可以预先配置选项并根据其依赖顺序覆盖选项值

                                    3、最后，你的模块可以执行 ExecutePreConfiguredActions
                                            eg:
                                                public override void ConfigureServices(ServiceConfigurationContext context)
                                                {
                                                    var options = context.Services.ExecutePreConfiguredActions<MyPreOptions>();
                                                    if (options.MyValue)
                                                    {
                                                        //...
                                                    }
                                                }
                    */


        </script>
    </body>
</html>